/* license section

Flash MiniBuilder is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Flash MiniBuilder is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Flash MiniBuilder.  If not, see <http://www.gnu.org/licenses/>.


Author: Victor Dramba
2009
*/
package ro.minibuilder.asparser {
	
	import com.ideas.data.DataHolder;
	
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.net.FileReference;
	import flash.net.SharedObject;
	import flash.text.TextField;
	import flash.utils.ByteArray;
	import flash.utils.getTimer;
	import flash.utils.setTimeout;
	
	import ro.minibuilder.swcparser.SWCParser;
	import ro.minibuilder.swcparser.SWFParser;
	import ro.victordramba.thread.ThreadEvent;
	import ro.victordramba.thread.ThreadsController;

	[Event(type = "flash.events.Event", name = "change")]
	public class Controller extends EventDispatcher {
		[Embed(source = "../../../assets/playerglobal_4.5_11.0.swc", mimeType = "application/octet-stream")] //most updated working version (playerglobal_4.0_10.1.swc)
		private static var PlayerglobalAsset:Class;
		//
		
		[Embed(source = "../../../assets/textLayout.swc", mimeType = "application/octet-stream")] //working
		private static var TextLayoutAsset:Class;
		//
		//[Embed(source = "../../../assets/Away3D-3.6.0-FlashPlayer10.swc", mimeType = "application/octet-stream")] //working
		//private static var Away3DAsset:Class;
		//
		//[Embed(source = "../../../assets/Box2D_2_1a.swc", mimeType = "application/octet-stream")] //working
		//private static var Box2D_2_1a:Class;
		//
		//[Embed(source = "../../../assets/airglobal.swc", mimeType = "application/octet-stream")] 
		//private static var AirGlobal:Class;
		
		private var parser:Parser;
		private var t0:Number;
		static private var tc:ThreadsController;
		public var status:String;
		public var percentReady:Number = 0;
		//public var tokenInfo:String;
		//public var scopeInfo:Array/*of String*/
		//public var typeInfo:Array/*of String*/
		private var fld:TextField;
		function Controller(stage:Stage, textField:TextField) {
			fld = textField;
			//TODO refactor, Controller should probably be a singleton
			if (!tc) {
				tc = new ThreadsController(stage);
				var db:TypeDB
				db = SWCParser.parse(new PlayerglobalAsset);//AirGlobal);//
				TypeDB.setDB('playerglobal', db);
				//db = SWCParser.parse(new Away3DAsset);
				//TypeDB.setDB('away', db);
				db = SWCParser.parse(new TextLayoutAsset);
				TypeDB.setDB('textLayout', db);
				//db = SWCParser.parse(new Box2D_2_1a);
				//TypeDB.setDB('Box2D_2_1a', db);
				//db = SWCParser.parse(new Alternativa3D);
				//TypeDB.setDB('Alternativa3D', db);
			}
			parser = new Parser;
			tc.addEventListener(ThreadEvent.THREAD_READY, function(e:ThreadEvent):void {
				if (e.thread != parser)
					return;
				
				//parser.updateFormating(DataHolder.mainFont,DataHolder.fontSize,DataHolder.backgroundColor);
				parser.applyFormats(fld);
				
				//cursorMoved(textField.caretIndex);
				status = 'Parse time: ' + (getTimer() - t0) + 'ms ' + parser.tokenCount + ' tokens';
				dispatchEvent(new Event('complete'));
			});
			tc.addEventListener(ThreadEvent.PROGRESS, function(e:ThreadEvent):void {
				if (e.thread != parser)
					return;
				status = '';
				percentReady = parser.percentReady;
				dispatchEvent(new Event('progress'));
			});
		}
		public function updateFormating():void{
			parser.updateFormating(DataHolder.mainFont,DataHolder.fontSize,DataHolder.backgroundColor);
			sourceChanged(fld.text);
		}
		public function saveTypeDB():void {
			/*var so:SharedObject = SharedObject.getLocal('ascc-type');
			so.data.typeDB = parser.getTypeData();
			so.flush();*/
			var file:FileReference = new FileReference;
			var ret:ByteArray = parser.getTypeData();
			file.save(ret, 'globals.amf');
		}
		public function restoreTypeDB():void {
			throw new Error('restoreTypeDB not supported');
			var so:SharedObject = SharedObject.getLocal('ascc-type');
			TypeDB.setDB('restored', so.data.typeDB);
		}
		/*public function addTypeDB(typeDB:TypeDB, name:String):void
		{
			parser.addTypeData(typeDB, name);
		}*/
		public function loadSWFLib(swfData:ByteArray, fileName:String):void {
			TypeDB.setDB(fileName, SWFParser.parse(swfData));
		}
		public function sourceChanged(source:String, fileName:String = ""):void {
			t0 = getTimer();
			
			parser.load(source, fileName);
			
			if (tc.isRunning(parser)){
				tc.kill(parser);
			}
			
			tc.run(parser);
			status = 'Processing ...';
		}
		public function getMemberList(index:int):Vector.<String> {
			return parser.newResolver().getMemberList(fld.text, index);
		}
		public function getFunctionDetails(index:int):String {
			return parser.newResolver().getFunctionDetails(fld.text, index);
		}
		public function getTypeOptions():Vector.<String> {
			return parser.newResolver().getAllTypes();
		}
		public function getAllOptions(index:int):Vector.<String> {
			return parser.newResolver().getAllOptions(index);
		}
		public function getMissingImports(name:String, pos:int):Vector.<String> {
			return parser.newResolver().getMissingImports(name, pos);
		}
		public function isInScope(name:String, pos:int):Boolean {
			return parser.newResolver().isInScope(name, pos);
		}
		public function findDefinition(index:int):Location {
			var field:Field = parser.newResolver().findDefinition(fld.text, index);
			if (!field)
				return null;
			for (var parent:Field = field, i:int = 0; parent && i < 10; parent = parent.parent, i++) {
				if (parent.sourcePath) {
					return new Location(parent.sourcePath, field.pos);
				}
			}
			return new Location(null, field.pos);
		}
	}
}